/*
 * Copyright  2018 Linkel Technology Co., Ltd, Beijing
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BA SIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
import {
    GET_LIST,
    GET_ONE,
    GET_MANY,
    GET_MANY_REFERENCE,
    CREATE,
    UPDATE,
    UPDATE_MANY,
    DELETE,
    DELETE_MANY,
} from "react-admin/lib";
import IndexDBRest from "./indexdbRest";
import adjustFormData from "./adjustFormData";

const log = (type, resource, params) => {
    console.log(`indexdbRest query:\n type: ${type}\n resource: ${resource}\n params: ${JSON.stringify(params)}`);
};

const schema = {
    accounts: "++id, &name, &creditCode, &mobile",
    keypairs: "++id, createdAt, ownerID, ownerCreditCode, &kp.sn, &cert.sn, status, name",
    certificate: "++id, &creditCodeCombineName, &sn",
};

// Init For test
const initData = {};
/*
    keypairs: [
        {kp: {sn: '1316EC91876CDEE5', alg: {name: 'EC', param: 'secp256r1'}}, cert: {sn: '12345678'}, createdAt: new Date(), status: false, ownerID: 1},
        {kp: {sn: '2316EC91876CDEE5', alg: {name: 'EC', param: 'secp256r1'}}, cert: {sn: '22345678'}, createdAt: new Date(), status: true, ownerID: 1},
        {kp: {sn: '3316EC91876CDEE5', alg: {name: 'EC', param: 'secp256k1'}}, cert: {sn: '32345678'}, createdAt: new Date(), status: true, ownerID: 1},
        {kp: {sn: '4316EC91876CDEE5', alg: {name: 'RSA', param: '1024'}}, cert: {sn: '42345678'}, createdAt: new Date(), status: true, ownerID: 1},
        {kp: {sn: '5316EC91876CDEE5', alg: {name: 'RSA', param: '2048'}}, cert: {sn: '52345678'}, createdAt: new Date(), status: true, ownerID: 1},
        {kp: {sn: '6316EC91876CDEE5', alg: {name: 'EC', param: 'secp256k1'}}, cert: {sn: '62345678'}, createdAt: new Date(), status: true, ownerID: 1},
        {kp: {sn: '7316EC91876CDEE5', alg: {name: 'EC', param: 'secp256k1'}}, cert: {sn: '72345678'}, createdAt: new Date(), status: false, ownerID: 1},
        {kp: {sn: '8316EC91876CDEE5', alg: {name: 'EC', param: 'secp256k1'}}, cert: {sn: '82345678'}, createdAt: new Date(), status: true, ownerID: 1},
        {kp: {sn: '9316EC91876CDEE5', alg: {name: 'EC', param: 'secp256k1'}}, cert: {sn: '92345678'}, createdAt: new Date(), status: true, ownerID: 1},
        {kp: {sn: '1416EC91876CDEE5', alg: {name: 'EC', param: 'secp256k1'}}, cert: {sn: '13345678'}, createdAt: new Date(), status: true, ownerID: 1},
        {kp: {sn: '1516EC91876CDEE5', alg: {name: 'EC', param: 'secp256k1'}}, cert: {sn: '14345678'}, createdAt: new Date(), status: true, ownerID: 1},
        {kp: {sn: '1616EC91876CDEE5', alg: {name: 'EC', param: 'secp256k1'}}, cert: {sn: '15345678'}, createdAt: new Date(), status: true, ownerID: 1},
        {kp: {sn: '1716EC91876CDEE5', alg: {name: 'EC', param: 'secp256k1'}}, cert: {sn: '16345678'}, createdAt: new Date(), status: true, ownerID: 1},
    ]
}
*/

export default async (type, resource, params) => {
    const indexdbRest = new IndexDBRest("BAR", 1, schema, initData);
    log(type, resource, params);

    let adjustedFormData;

    switch (type) {
        case GET_LIST: {
            const { page, perPage } = params.pagination;
            const { field, order } = params.sort;
            const query = {
                filter: await adjustFormData(type, resource, params.filter),
                sort: [field, order],
                range: [(page - 1) * perPage, page * perPage - 1],
            };
            return indexdbRest.getCollection(resource, query).then((r) => ({ 
                data: r.result, total: r.totalCount,
            }));
        }
        case GET_MANY: {
            const { page = 1, perPage = 25 } = params.pagination || {};
            const manyFilter = { id: ["in", params.ids] };
            const { field = "id", order = "DESC" } = params.sort || {};
            const query = {
                filter: await adjustFormData(type, resource, { ...params.filter, ...manyFilter }),
                sort: [field, order],
                range: [(page - 1) * perPage, page * perPage - 1],
            };
            return indexdbRest.getCollection(resource, query).then((r) => ({ 
                data: r.result, total: r.totalCount,
            }));
        }
        case GET_MANY_REFERENCE: {
            const { target, id } = params;
            const referenceFilter = {};
            referenceFilter[target] = ["equal", id];
            const { page, perPage } = params.pagination;
            const { field, order } = params.sort;
            const query = {
                filter: await adjustFormData(type, resource, { ...params.filter, ...referenceFilter }),
                sort: [field, order],
                range: [(page - 1) * perPage, page * perPage - 1],
            };
            return indexdbRest.getCollection(resource, query).then((r) => ({ 
                data: r.result, total: r.totalCount,
            }));
        }
        case GET_ONE: {
            const gID = parseInt(params.id, 10);
            return indexdbRest.getOne(resource, gID).then((r) => ({ data: r.result }));
        }
        case CREATE: {
            const d = params.data;
            adjustedFormData = await adjustFormData(type, resource, d);
            return indexdbRest.create(resource, adjustedFormData)
                .then((r) => ({ data: r.result }))
                .catch((e) => {
                    if (/uniqueness requirements/.test(e.message)) {
                        return Promise.reject(new Error(`${resource === "keypairs" ? "密钥对" : "账号"}已存在！`));
                    }
                    return Promise.reject(e);
                });
        }
        case UPDATE: {
            const uID = parseInt(params.id, 10);
            const uData = params.data;

            return indexdbRest.update(resource, uID, uData).then((r) => ({ data: r.result }));
        }
        case DELETE: {
            const dID = parseInt(params.id, 10);
            return indexdbRest.delete(resource, dID).then((r) => ({ data: r.result }));
        }
        case "GET_COUNT": {
            return indexdbRest.getCount(resource);
        }
        default:
            throw new Error(`Unsupported data provider request type ${type}`);
    }
};
